package com.mallcloud.mall.mall.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mallcloud.mall.common.core.constant.CacheConstants;
import com.mallcloud.mall.common.core.exception.ErrorCodes;
import com.mallcloud.mall.common.core.exception.FailException;
import com.mallcloud.mall.common.core.util.MsgUtils;
import com.mallcloud.mall.mall.api.entity.MallProductCategoryModel;
import com.mallcloud.mall.mall.mapper.MallProductCategoryMapper;
import com.mallcloud.mall.mall.service.MallProductCategoryService;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 商品分类
 */
@Service
public class MallProductCategoryServiceImpl extends ServiceImpl<MallProductCategoryMapper, MallProductCategoryModel> implements MallProductCategoryService {

	@Override
	@Cacheable(value = CacheConstants.PROJECT_CATEGORY_DETAILS, key = "#categoryName",  unless = "#result.isEmpty()")
	public List<Tree<Long>> selectTree(Long parentId, String categoryName) {
		// 查询全部分类
		List<MallProductCategoryModel> proCategoryList = this.list(
				Wrappers.<MallProductCategoryModel>lambdaQuery()
						.like(StrUtil.isNotBlank(categoryName), MallProductCategoryModel::getName, categoryName)
						.orderByAsc(MallProductCategoryModel::getSortOrder)
		);
		List<TreeNode<Long>> collect = proCategoryList.stream()
				.sorted(Comparator.comparingInt(MallProductCategoryModel::getSortOrder))
				.map(getNodeFunction()).collect(Collectors.toList());

		// 模糊查询 不组装树结构 直接返回 表格方便编辑
		if (StrUtil.isNotBlank(categoryName)) {
			return collect.stream().map(node -> {
						Tree<Long> tree = new Tree<>();
						tree.putAll(node.getExtra());
						BeanUtils.copyProperties(node, tree);
						return tree;
					}
			).collect(Collectors.toList());
		}

		return TreeUtil.build(collect, 0L);
	}

	@Override
	@CacheEvict(value = {CacheConstants.PROJECT_CATEGORY_DETAILS,
						 CacheConstants.PROJECT_CATEGORY_TREE,
						 CacheConstants.PROJECT_CATEGORY_FIRST,
						 CacheConstants.PROJECT_CATEGORY_THIRD}, allEntries = true)
	public Boolean removeCategoryById(Long categoryId) {
		// 查询父节点为当前节点的节点
		long count = this.count(Wrappers.<MallProductCategoryModel>query().lambda().eq(MallProductCategoryModel::getParentId, categoryId));
		if (count > 0) {
			throw new FailException(MsgUtils.getMessage(ErrorCodes.SYS_CATEGORY_DELETE_EXISTING));
		}

		return this.removeById(categoryId);
	}

	@Override
	@CacheEvict(value = {CacheConstants.PROJECT_CATEGORY_DETAILS,
						 CacheConstants.PROJECT_CATEGORY_TREE,
						 CacheConstants.PROJECT_CATEGORY_FIRST,
						 CacheConstants.PROJECT_CATEGORY_THIRD}, allEntries = true)
	public Boolean updateCategoryById(MallProductCategoryModel dto) {
		return this.updateById(dto);
	}

	@Override
	@CacheEvict(value = {CacheConstants.PROJECT_CATEGORY_DETAILS,
						 CacheConstants.PROJECT_CATEGORY_TREE,
						 CacheConstants.PROJECT_CATEGORY_FIRST,
						 CacheConstants.PROJECT_CATEGORY_THIRD}, allEntries = true)
	public Boolean saveCategory(MallProductCategoryModel dto) {
		return this.save(dto);
	}

	@NotNull
	private Function<MallProductCategoryModel, TreeNode<Long>> getNodeFunction() {
		return proCategory -> {
			TreeNode<Long> node = new TreeNode<>();
			node.setId(proCategory.getCategoryId());
			node.setName(proCategory.getName());
			node.setParentId(proCategory.getParentId());
			node.setWeight(proCategory.getSortOrder());
			// 扩展属性
			Map<String, Object> extra = new HashMap<>();
			if (StrUtil.isNotBlank(proCategory.getIcon())) {
				extra.put("icon", proCategory.getIcon());
			}
			if (StrUtil.isNotBlank(proCategory.getImgUrl())) {
				extra.put("imgUrl", proCategory.getImgUrl());
			}
			extra.put("status", proCategory.getStatus());
			extra.put("label", proCategory.getName());
			extra.put("classificationLevel", proCategory.getClassificationLevel());
			extra.put("sortOrder", proCategory.getSortOrder());
			node.setExtra(extra);
			return node;
		};
	}
}
